package com.junyi.basis;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

/**
 * BigDecimal 类的使用
 * @time: 2021年12月17日 10:26
 * @author: junyi Xu
 */
@Slf4j
public class BigDecimalMy {

    /** 使用float / double 会精度的问题 */
    @Test
    public void wrong() {
        float a = 1.0f - 0.9f;
        float b = 0.9f - 0.8f;
        System.out.println(a);      // 0.100000024
        System.out.println(b);      // 0.099999964
        System.out.println(a == b);     // false
    }

    /** 基本运算 */
    @Test
    public void basic() {
        BigDecimal a = new BigDecimal("1.0");
        BigDecimal b = new BigDecimal("0.9");
        System.out.println(a.add(b));       // 1.9
        System.out.println(a.subtract(b));      // 0.1
        System.out.println(a.multiply(b));      // 0.90
        // System.out.println(a.divide(b));        // 无法除尽，抛出 ArithmeticException 异常
        // 调用 divide 方法应该使用 3 个参数的方法
        System.out.println(a.divide(b, 2, RoundingMode.HALF_UP));       // 1.11
    }


    // 大小比较。返回 -1 表示 a 小于 b，0 表示 a 等于 b ，1 表示 a 大于 b。
    @Test
    public void compare() {
        BigDecimal a = new BigDecimal("1.0");
        BigDecimal b = new BigDecimal("0.9");
        System.out.println(a.compareTo(b));     // 1


        BigDecimal c = new BigDecimal("1.0");
        BigDecimal d = new BigDecimal("1");
        System.out.println(c.compareTo(d));     // 0
    }

    // 设置精度
    @Test
    public void setScale() {
        BigDecimal m = new BigDecimal("1.55");
        BigDecimal n = m.setScale(1, RoundingMode.HALF_DOWN);
        System.out.println(n);// 1.5

        n = m.setScale(1, RoundingMode.HALF_UP);
        System.out.println(n);// 1.6
    }

    // BigDecimal 集合问题
    // BigDecimal的HashMap或者HashSet，其会调用equal()或hashCode()，即会考虑BigDecimal的Value和Scale，会导致问题
    @Test
    public void collection() {
        // 问题
        Set<BigDecimal> hashSet1 = new HashSet<>();
        hashSet1.add(new BigDecimal("1.0"));
        System.out.println(hashSet1.contains(new BigDecimal("1")));     //返回false

        // 解决方法一：使用TreeSet，其使用的是compareTo()
        Set<BigDecimal> treeSet = new TreeSet<>();
        treeSet.add(new BigDecimal("1.0"));
        System.out.println(treeSet.contains(new BigDecimal("1")));      //返回true

        // 解决方法二：放入前去掉0，比较的时候也去掉0，调用stripTrailingZeros()
        Set<BigDecimal> hashSet2 = new HashSet<>();
        hashSet2.add(new BigDecimal("1.0").stripTrailingZeros());
        System.out.println(hashSet2.contains(new BigDecimal("1.000").stripTrailingZeros()));    //返回true

    }

}
